#ifndef __VBM_H__
#define __VBM_H__

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
#include <string>
#include <string.h>
#include <GL/glew.h>
#include <iostream>

typedef struct VBM_HEADER_t
{
    unsigned int magic;
    unsigned int size;
    char name[64];
    unsigned int num_attribs;
    unsigned int num_frames;
    unsigned int num_vertices;
    unsigned int num_indices;
    unsigned int index_type;
    unsigned int num_materials;
    unsigned int flags;
} VBM_HEADER;

typedef struct VBM_ATTRIB_HEADER_t
{
    char name[64];
    unsigned int type;
    unsigned int components;
    unsigned int flags;
} VBM_ATTRIB_HEADER;

typedef struct VBM_FRAME_HEADER_t
{
    unsigned int first;
    unsigned int count;
    unsigned int flags;
} VBM_FRAME_HEADER;

class VbmObject{
    protected:
        unsigned char* file_data;
        unsigned char* vertex_data;
        unsigned int vertex_num;
        GLuint VAO, VBO;
               
    public:
        bool loadFromVBM(const char * filename){
            std::cout << "File name: " << filename << std::endl;
            FILE * f = NULL;
            f = fopen(filename, "rb");
            if(f == NULL)
                return false;

            fseek(f, 0, SEEK_END);
            size_t filesize = ftell(f);
            fseek(f, 0, SEEK_SET);

            file_data = new unsigned char [filesize];
            fread(file_data, filesize, 1, f);
            fclose(f);

            VBM_HEADER * header = (VBM_HEADER *)file_data;
            vertex_data = file_data + header->size + header->num_attribs * sizeof(VBM_ATTRIB_HEADER) + header->num_frames * sizeof(VBM_FRAME_HEADER);
            vertex_num = header->num_vertices;
            std::cout << "Num of Vertices: " << vertex_num << std::endl;

            return true;
        }

        void setup(){
            glCreateVertexArrays(1, &VAO);
            glBindVertexArray(VAO);
            glCreateBuffers(1, &VBO);
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glNamedBufferStorage(VBO, 9*sizeof(GLfloat)*vertex_num, vertex_data, 0);
            glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
            glEnableVertexAttribArray(0);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(GLfloat)*vertex_num*4));
            glEnableVertexAttribArray(1);
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(GLfloat)*vertex_num*3));
            glEnableVertexAttribArray(2);
        }

        void render(){
            glBindVertexArray(VAO);
            glDrawArrays(GL_TRIANGLES, 0, vertex_num);
        }

        ~VbmObject(){
            if(file_data != NULL){
                delete file_data;
            }
        }
};

#endif
